package net

import (
	"github.com/gorilla/websocket"
	"msgserver/server/game/logic/conn"
	"msgserver/server/game/logic/pos"
	"sync"
)

var Mgr = &WsMgr{
	userCache: make(map[int]WSConn),
	connCache: make(map[int64]WSConn),
	roleCache: make(map[int]WSConn),
}

type WsMgr struct {
	uc sync.RWMutex
	cc sync.RWMutex
	rc sync.RWMutex

	userCache map[int]WSConn
	connCache map[int64]WSConn
	roleCache map[int]WSConn
}

func (m *WsMgr) UserLogin(conn WSConn, uid int, token string) {
	m.uc.Lock()
	defer m.uc.Unlock()
	oldConn := m.userCache[uid]
	if oldConn != nil {
		if conn != oldConn {
			// 通过旧客户端 有用户抢登录了
			oldConn.Push("robLogin", nil) //name固定为"robLogin"代表出现重复登陆
		}
	}
	// 将新连接存入缓存
	m.userCache[uid] = conn
	conn.SetProperty("uid", uid)
	conn.SetProperty("token", token)
}

func (m *WsMgr) RoleEnter(conn WSConn, rid int) {
	m.rc.Lock()
	defer m.rc.Unlock()
	m.roleCache[rid] = conn

}

func (w *WsMgr) PushByRoleId(rid int, msgName string, data interface{}) bool {
	if rid <= 0 {
		return false
	}
	w.rc.Lock()
	defer w.rc.Unlock()
	c, ok := w.roleCache[rid]
	if ok {
		c.Push(msgName, data)
		return true
	} else {
		return false
	}
}

func (w *WsMgr) Push(pushSync conn.PushSync) {

	model := pushSync.ToModel()
	belongRIds := pushSync.BelongToRId()
	isCellView := pushSync.IsCellView()
	x, y := pushSync.Position()
	cells := make(map[int]int)

	//推送给开始位置
	if isCellView {
		cellRIds := pos.RPMgr.GetCellRoleIds(x, y, 8, 6)
		for _, rid := range cellRIds {
			//是否能出现在视野
			if can := pushSync.IsCanView(rid, x, y); can {
				w.PushByRoleId(rid, pushSync.PushMsgName(), model)
				cells[rid] = rid
			}
		}
	}

	//推送给目标位置
	tx, ty := pushSync.TPosition()
	if tx >= 0 && ty >= 0 {
		var cellRIds []int
		if isCellView {
			cellRIds = pos.RPMgr.GetCellRoleIds(tx, ty, 8, 6)
		} else {
			cellRIds = pos.RPMgr.GetCellRoleIds(tx, ty, 0, 0)
		}

		for _, rid := range cellRIds {
			if _, ok := cells[rid]; ok == false {
				if can := pushSync.IsCanView(rid, tx, ty); can {
					w.PushByRoleId(rid, pushSync.PushMsgName(), model)
					cells[rid] = rid
				}
			}
		}
	}

	//推送给自己
	for _, rid := range belongRIds {
		if _, ok := cells[rid]; ok == false {
			w.PushByRoleId(rid, pushSync.PushMsgName(), model)
		}
	}
}

var cid int64

func (w *WsMgr) NewConn(wsConn *websocket.Conn, needSecret bool) *wsServer {

	s := NewWsServer(wsConn, needSecret)
	cid++
	s.SetProperty("cid", cid)
	w.connCache[cid] = s
	return s
}

func NewWsServer(wsConn *websocket.Conn, needSecret bool) *wsServer {
	s := &wsServer{
		wsConn:     wsConn,
		outChan:    make(chan *WsMsgRsp, 1000),
		property:   make(map[string]interface{}),
		Seq:        0,
		needSecret: needSecret,
	}
	cid++
	s.SetProperty("cid", cid)
	return s
}
